Climbing stairs [Matrix Exponentiation]¶
Time: O(LogN); Space: O(1); easy
You are climbing a stair case. It takes n steps to reach to the top.
Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?
Note:
Given n will be a positive integer.
Example 1:
Input: 2
Output: 2
Explanation:
There are two ways to climb to the top.
1 step + 1 step
2 steps
Example 2:
Input: 3
Output: 3
Explanation:
There are three ways to climb to the top.
1 step + 1 step + 1 step
1 step + 2 steps
2 steps + 1 step
Hints:
To reach nth step, what could have been your previous steps? (Think about the step sizes)
[9]:
class Solution1(object):
"""
Time: O(LogN)
Space: O(1)
"""
class Solution1(object):
"""
Time: O(LogN)
Space: O(1)
"""
def climbStairs(self, n):
"""
:type n: int
:rtype: int
"""
def matrix_mult(m1, m2):
return [[sum(a * b for a, b in zip(m1_row, m2_col)) for m2_col in zip(*m2)] for m1_row in m1]
def identity(size):
size = range(size)
return [[(i == j) * 1 for i in size] for j in size]
def matrix_exp(m, pow):
assert pow >= 0 and int(pow) == pow, "Only non-negative, integer powers allowed"
accumulator = identity(len(m))
for i in range(pow):
accumulator = matrix_mult(accumulator, m)
return accumulator
def print_table(data):
for row in data:
print(' '.join('%-5s' % ('%s' % cell) for cell in row))
T = [[1, 1],
[1, 0]]
m_exp = matrix_exp(T, n) # n=2: m_exp=[[2, 1], [1, 1]]; n=3: m_exp[[3, 2], [2, 1]]
res = matrix_mult([[1, 0]], m_exp) # n=2: res=[[2, 1]]; n=3: res=[[2, 1]]; [[3, 2]]
return res[0][0]
[10]:
s = Solution1()
n = 2
assert s.climbStairs(n) == 2
n = 3
assert s.climbStairs(n) == 3
[11]:
class Solution2(object):
def climbStairs(self, n):
"""
:type n: int
:rtype: int
"""
prev, current = 0, 1
for i in range(n):
prev, current = current, prev + current,
return current
[12]:
s = Solution2()
n = 2
assert s.climbStairs(n) == 2
n = 3
assert s.climbStairs(n) == 3